#include "uesdk/http/http_connect.h"
#include "uesdk/user_manger.h"
#include "uesdk/cJSON.h"
#include "uesdk/error.h"
#include "uesdk/uesdk.h"
#include "uesdk/utils.h"
#include <iostream>

namespace uesdk {

static uesdk::http::HttpConnectionPool::ptr s_qtch_conn_ptr = uesdk::http::HttpConnectionPool::Create(UESDK_SERVER_URL,UESDK_SERVER_HOST);

User::User(int32_t id){
    m_id = id;
}

void User::del(const std::string& key) {
    MutexType::Lock lock(m_mutex);
    m_data.erase(key);
}

bool User::has(const std::string& key) {
    MutexType::Lock lock(m_mutex);
    std::map<std::string, boost::any>::iterator it = m_data.find(key);
    return it!=m_data.end();
}

bool User::getSelfUserMessage(){
    if(!checkAndRefreshToken()){
        return false;
    }
    std::string id = getData<std::string>("id");
    std::string url = UESDK_SERVER_URL "/user/get?id=" + id;
    std::map<std::string,std::string> headers;
    headers["token"] = getData<std::string>("token");
    uesdk::http::HttpResult::ptr request_res = s_qtch_conn_ptr->DoGet(url,5000,headers);
    if(request_res->m_result != uesdk::http::HttpResult::Error::OK){
        return false;
    }
    cJSON* body_cjson = cJSON_Parse(request_res->m_resonse->getBody().c_str());
    cJSON* code = cJSON_GetObjectItem(body_cjson,"code");
    if(!code|| strcmp("0",code->valuestring)!=0){
        std::cout << "login error response:[\n" << request_res->m_resonse << "]" << std::endl;
        return false;
    }
#define XX(c_data_name,c_name,json_key,key) \
    cJSON* c_name = cJSON_GetObjectItem(c_data_name,#json_key); \
    if(c_name){ \
        setData<std::string>(#key,c_name->valuestring); \
    }

    XX(body_cjson,userNick,userNick,userNick);
    XX(body_cjson,tel,tel,tel);
    XX(body_cjson,created_at,created_at,created_at);

#undef XX

    return true;

}

bool User::getNewToken() {
    std::string flashToken = getData<std::string>("flashToken","");
    if(flashToken.empty()){
        return false;
    }
    std::string url = UESDK_SERVER_URL "/user/login/flashtoken?flashToken=" + flashToken;
    uesdk::http::HttpResult::ptr request_res = s_qtch_conn_ptr->DoGet(url,5000);
    if(request_res->m_result != uesdk::http::HttpResult::Error::OK){
        return false;
    }
    cJSON* body_cjson = cJSON_Parse(request_res->m_resonse->getBody().c_str());
    cJSON* code = cJSON_GetObjectItem(body_cjson,"code");
    if(!code|| strcmp("0",code->valuestring)!=0){
        std::cout << "login error response:[\n" << request_res->m_resonse << "]" << std::endl;
        return false;
    }
    cJSON* data = cJSON_GetObjectItem(body_cjson,"data");
    cJSON* c_token = cJSON_GetObjectItem(data,"token");
    setData<std::string>("token",c_token->valuestring);
    setData<uint64_t>("tokenExpire",time(NULL)+1800);
    return true;
}

bool User::isTokenExpire() {
    uint64_t tokenExpire = getData<uint64_t>("tokenExpire",0);
    if(tokenExpire<=(uint64_t)time(NULL)){
        return true;
    }
    return false;
}

bool User::checkAndRefreshToken(bool force) {
    if(force || isTokenExpire()){
        return getNewToken();
    }
    return true;
}

void UserManger::add(User::ptr data) {
    if(data){
        MutexType::Lock lock(m_mutex);
        m_data[data->getId()] = data;
    }
}

void UserManger::del(int32_t id) {
    MutexType::Lock lock(m_mutex);
    m_data.erase(id);
}

void UserManger::del(std::vector<int32_t>& ids) {
    MutexType::Lock lock(m_mutex);
    for(size_t i = 0; i < ids.size(); ++i){
        m_data.erase(ids[i]);
    }
}

User::ptr UserManger::get(int32_t id) {
    MutexType::Lock lock(m_mutex);
    std::map<int32_t, User::ptr>::iterator it = m_data.find(id);
    if(it==m_data.end()){
        return User::ptr();
    }
    return it->second;
}

User::ptr UserManger::login(const std::string& user_name,const std::string& password) {
    std::string url = UESDK_SERVER_URL "/user/login/pwd?userName=" + user_name + "&passWord=" + password;
    uesdk::http::HttpResult::ptr login_res = s_qtch_conn_ptr->DoGet(url,5000);
    if(login_res->m_result != uesdk::http::HttpResult::Error::OK){
        return User::ptr();
    }
    cJSON* login_cjson = cJSON_Parse(login_res->m_resonse->getBody().c_str());
    cJSON* code = cJSON_GetObjectItem(login_cjson,"code");
    if(!code|| strcmp("0",code->valuestring)!=0){
        std::cout << "login error response:[\n" << login_res->m_resonse << "]" << std::endl;
        cJSON_Delete(login_cjson);
        return User::ptr();
    }
    cJSON* data = cJSON_GetObjectItem(login_cjson,"data");
    cJSON* c_token = cJSON_GetObjectItem(data,"token");
    cJSON* c_flash_token = cJSON_GetObjectItem(data,"flashToken");
    cJSON* c_id = cJSON_GetObjectItem(data,"id");
    User::ptr user = boost::make_shared<User>(c_id->valueint);
    UserMgr::GetInstance()->add(user);
    user->setData<std::string>("token",c_token->valuestring);
    user->setData<std::string>("flashToken",c_flash_token->valuestring);
    user->setData<std::string>("userName",user_name);
    user->setData<std::string>("password",password);

    user->setData<uint64_t>("tokenExpire",time(NULL)+1800);
    cJSON_Delete(login_cjson);

    return user;

}

User::ptr UserManger::loginByVerifyTel(const std::string& tel,const std::string& verifyCode){
    if(!TypeUtil::isPhoneNumber(tel)){
        return User::ptr();
    }
    std::string url = UESDK_SERVER_URL "/user/login/tel?phone=" + tel + "&code=" + verifyCode;
    uesdk::http::HttpResult::ptr login_res = s_qtch_conn_ptr->DoGet(url,5000);
    if(login_res->m_result != uesdk::http::HttpResult::Error::OK){
        return User::ptr();
    }
    cJSON* login_cjson = cJSON_Parse(login_res->m_resonse->getBody().c_str());
    cJSON* code = cJSON_GetObjectItem(login_cjson,"code");
    if(!code|| strcmp("0",code->valuestring)!=0){
        std::cout << "login error response:[\n" << login_res->m_resonse << "]" << std::endl;
        cJSON_Delete(login_cjson);
        return User::ptr();
    }
    cJSON* data = cJSON_GetObjectItem(login_cjson,"data");
    cJSON* c_token = cJSON_GetObjectItem(data,"token");
    cJSON* c_flash_token = cJSON_GetObjectItem(data,"flashToken");
    cJSON* c_id = cJSON_GetObjectItem(data,"id");
    User::ptr user = boost::make_shared<User>(c_id->valueint);
    UserMgr::GetInstance()->add(user);
    user->setData<std::string>("token",c_token->valuestring);
    user->setData<std::string>("flashToken",c_flash_token->valuestring);
    user->setData<uint64_t>("tokenExpire",time(NULL)+1800);
    cJSON_Delete(login_cjson);
    return user;
}

User::ptr UserManger::loginByFlashToken(const std::string& flashToken){
    std::string url = UESDK_SERVER_URL "/user/login/flashtoken?flashToken=" + flashToken;
    uesdk::http::HttpResult::ptr login_res = s_qtch_conn_ptr->DoGet(url,5000);
    if(login_res->m_result != uesdk::http::HttpResult::Error::OK){
        return User::ptr();
    }
    cJSON* login_cjson = cJSON_Parse(login_res->m_resonse->getBody().c_str());
    cJSON* code = cJSON_GetObjectItem(login_cjson,"code");
    if(!code|| strcmp("0",code->valuestring)!=0){
        std::cout << "login error response:[\n" << login_res->m_resonse << "]" << std::endl;
        cJSON_Delete(login_cjson);
        return User::ptr();
    }
    cJSON* data = cJSON_GetObjectItem(login_cjson,"data");
    cJSON* c_token = cJSON_GetObjectItem(data,"token");
    cJSON* c_id = cJSON_GetObjectItem(data,"id");
    User::ptr user = boost::make_shared<User>(c_id->valueint);
    UserMgr::GetInstance()->add(user);
    user->setData<std::string>("token",c_token->valuestring);
    user->setData<std::string>("flashToken",flashToken);
    user->setData<uint64_t>("tokenExpire",time(NULL)+1800);
    cJSON_Delete(login_cjson);
    return user;
}

User::ptr UserManger::thirdLogin(const std::string& third_name) {
    ThirdPlateName plateName = StringToThirdPlate(third_name.c_str());
    if(plateName==ThirdPlateName::THIRD_ERROR){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_PARAM_ERROR,"third_name not exited");
        return User::ptr();
    }
    std::string url = UESDK_SERVER_URL "/api/third/author?third=" + third_name;
    uesdk::http::HttpResult::ptr login_res = s_qtch_conn_ptr->DoGet(url,5000);
    if(login_res->m_result != uesdk::http::HttpResult::Error::OK){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_REQUEST_ERROR,"third author request error:" + login_res->m_error);
        return User::ptr();
    }
    cJSON* login_cjson = cJSON_Parse(login_res->m_resonse->getBody().c_str());
    cJSON* code = cJSON_GetObjectItem(login_cjson,"code");
    if(!code|| strcmp("0",code->valuestring)!=0){
        cJSON* msg = cJSON_GetObjectItem(login_cjson,"msg");
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_REQUEST_ERROR,"third author faile:" + std::string(msg->valuestring));
        cJSON_Delete(login_cjson);
        return User::ptr();
    }
    cJSON* data = cJSON_GetObjectItem(login_cjson,"data");
    cJSON* c_code = cJSON_GetObjectItem(data,"code");
    cJSON* c_authorUrl = cJSON_GetObjectItem(data,"authorUrl");
    cJSON* c_verifyCode = cJSON_GetObjectItem(data,"verifyCode");
    User::ptr user = boost::make_shared<User>(-1);
    user->setData<std::string>("code",c_code->valuestring);
    user->setData<std::string>("authorUrl",c_authorUrl->valuestring);
    user->setData<std::string>("verifyCode",c_verifyCode->valuestring);
    cJSON_Delete(login_cjson);
    return user;
}

bool UserManger::phoneSmsVerify(const std::string& phone,VerifyType type){
    std::string smsType = VerifyTypeToString(type);
    if(phone.empty() || smsType == "error") {
        return false;
    }
    std::string url = UESDK_SERVER_URL "/user/sms/verify?smsType=" + smsType + "&phone=" + phone;
    uesdk::http::HttpResult::ptr login_res = s_qtch_conn_ptr->DoGet(url,5000);
    if(login_res->m_result != uesdk::http::HttpResult::Error::OK){
        return false;
    }
    cJSON* login_cjson = cJSON_Parse(login_res->m_resonse->getBody().c_str());
    cJSON* code = cJSON_GetObjectItem(login_cjson,"code");
    if(!code|| strcmp("0",code->valuestring)!=0){
        return false;
    }
    return true;
}

bool UserManger::emailSmsVerify(const std::string& email,VerifyType type){
    std::string smsType = VerifyTypeToString(type);
    if(email.empty() || smsType == "error") {
        return false;
    }
    std::string url = UESDK_SERVER_URL "/user/email/verify?smsType=" + smsType + "&email=" + email;
    uesdk::http::HttpResult::ptr http_res = s_qtch_conn_ptr->DoGet(url,5000);
    if(http_res->m_result != uesdk::http::HttpResult::Error::OK){
        return false;
    }
    cJSON* http_cjson = cJSON_Parse(http_res->m_resonse->getBody().c_str());
    cJSON* code = cJSON_GetObjectItem(http_cjson,"code");
    if(!code|| strcmp("0",code->valuestring)!=0){
        return false;
    }
    return true;
}

User::ptr UserManger::thirdLoginCheck(const std::string& third_name, const std::string& code,const std::string& verifyCode){
    ThirdPlateName plateName = StringToThirdPlate(third_name.c_str());
    if(plateName==ThirdPlateName::THIRD_ERROR){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_PARAM_ERROR,"third_name not exited");
        return User::ptr();
    }
    std::string url = UESDK_SERVER_URL "/api/third/login/check?third=" + third_name + "&code=" + code + "&verifyCode=" + verifyCode;
    uesdk::http::HttpResult::ptr login_res = s_qtch_conn_ptr->DoGet(url,5000);
    if(login_res->m_result != uesdk::http::HttpResult::Error::OK){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_REQUEST_ERROR,"third check request error:" + login_res->m_error);
        return User::ptr();
    }
    cJSON* body_cjson = cJSON_Parse(login_res->m_resonse->getBody().c_str());
    cJSON* c_code = cJSON_GetObjectItem(body_cjson,"code");
    if(!c_code|| strcmp("0",c_code->valuestring)!=0){
        cJSON* msg = cJSON_GetObjectItem(body_cjson,"msg");
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_REQUEST_ERROR,"third author faile:" + std::string(msg->valuestring));
        cJSON_Delete(body_cjson);
        return User::ptr();
    }
    cJSON* data_cjson = cJSON_GetObjectItem(body_cjson,"data");
    cJSON* c_token = cJSON_GetObjectItem(data_cjson,"token");
    cJSON* c_flash_token = cJSON_GetObjectItem(data_cjson,"flashToken");
    cJSON* c_id = cJSON_GetObjectItem(data_cjson,"id");
    User::ptr user = boost::make_shared<User>(c_id->valueint);
    UserMgr::GetInstance()->add(user);
    user->setData<std::string>("token",c_token->valuestring);
    user->setData<std::string>("flashToken",c_flash_token->valuestring);

    user->setData<uint64_t>("tokenExpire",time(NULL)+1800);
    cJSON_Delete(body_cjson);
    return user;
}

bool UserManger::createUserByTel(const std::string& user_name,const std::string& password,const std::string& tel,const std::string& verifyCode) {
    if(user_name.empty() || password.empty() || tel.empty() || verifyCode.empty()){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_PARAM_ERROR,"param couldn't be empty");
        return false;
    }
    cJSON* root = cJSON_CreateObject();
    cJSON_AddStringToObject(root,"userName",user_name.c_str());
    cJSON_AddStringToObject(root,"user_password",password.c_str());
    cJSON_AddStringToObject(root,"tel",tel.c_str());
    cJSON_AddStringToObject(root,"verifyCode",verifyCode.c_str());
    std::string body(cJSON_Print(root));
    cJSON_Delete(root);
    std::string url = UESDK_SERVER_URL "/user/create";
    std::map<std::string, std::string> header;
    uesdk::http::HttpResult::ptr login_res = s_qtch_conn_ptr->DoGet(url, 5000, header, body);
    if(login_res->m_result != uesdk::http::HttpResult::Error::OK){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_REQUEST_ERROR,"user register request error:" + login_res->m_error);
        return false;
    }
    cJSON* body_cjson = cJSON_Parse(login_res->m_resonse->getBody().c_str());
    cJSON* c_code = cJSON_GetObjectItem(body_cjson,"code");
    if(!c_code|| strcmp("0",c_code->valuestring)!=0){
        cJSON* msg = cJSON_GetObjectItem(body_cjson,"msg");
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_REQUEST_ERROR,"user register faile:" + std::string(msg->valuestring));
        cJSON_Delete(body_cjson);
        return false;
    }
    cJSON_Delete(body_cjson);
    return true;


}

bool UserManger::createUserByEmail(const std::string& user_name,const std::string& password,const std::string& email,const std::string& verifyCode) {
    if(user_name.empty() || password.empty() || email.empty() || verifyCode.empty()){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_PARAM_ERROR,"param couldn't be empty");
        return false;
    }
    cJSON* root = cJSON_CreateObject();
    cJSON_AddStringToObject(root,"userName",user_name.c_str());
    cJSON_AddStringToObject(root,"user_password",password.c_str());
    cJSON_AddStringToObject(root,"email",email.c_str());
    cJSON_AddStringToObject(root,"verifyCode",verifyCode.c_str());
    std::string body(cJSON_Print(root));
    cJSON_Delete(root);
    std::string url = UESDK_SERVER_URL "/user/create";
    std::map<std::string, std::string> header;
    uesdk::http::HttpResult::ptr login_res = s_qtch_conn_ptr->DoGet(url, 5000, header, body);
    if(login_res->m_result != uesdk::http::HttpResult::Error::OK){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_REQUEST_ERROR,"user register request error:" + login_res->m_error);
        return false;
    }
    cJSON* body_cjson = cJSON_Parse(login_res->m_resonse->getBody().c_str());
    cJSON* c_code = cJSON_GetObjectItem(body_cjson,"code");
    if(!c_code|| strcmp("0",c_code->valuestring)!=0){
        cJSON* msg = cJSON_GetObjectItem(body_cjson,"msg");
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_REQUEST_ERROR,"user register aile:" + std::string(msg->valuestring));
        cJSON_Delete(body_cjson);
        return false;
    }
    cJSON_Delete(body_cjson);
    return true;
}

    

}

#ifdef __cplusplus
extern "C" {
#endif


void UeUserInit(UeUser* user) {
    if(!user){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_PARAM_ERROR,"param can't be NULL");
        return;
    }
    user->id = -1;
}

int UeUserLogin(UeUser* user,char* user_name,char* password){
    if(!user || !user_name || !password){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_PARAM_ERROR,"param can't be NULL");
        return 0;
    }
    if(user->id != -1) {
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_REPEAT_LOGIN,"can't repeat login");
        return 0;
    }
    uesdk::User::ptr user_ptr = uesdk::UserManger::login(user_name,password);
    if(!user_ptr){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_LOGIN_FAILe,"login faile");
        return 0;
    }
    user->id = user_ptr->getId();
    return 1;
}

int UeUserLoginByTel(UeUser* user,char* tel,char* code){
    if(!user || !tel || !code){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_PARAM_ERROR,"param can't be NULL");
        return 0;
    }
    if(user->id != -1) {
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_REPEAT_LOGIN,"can't repeat login");
        return 0;
    }
    uesdk::User::ptr user_ptr = uesdk::UserManger::loginByVerifyTel(tel,code);
    if(!user_ptr){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_LOGIN_FAILe,"login faile");
        return 0;
    }
    user->id = user_ptr->getId();
    return 1;
}

int UeUserLoginByFlashToken(UeUser* user,char* flashToken,size_t flashTokenSize){
    if(!user || !flashToken || flashTokenSize <= 0){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_PARAM_ERROR,"param can't be NULL");
        return 0;
    }
    if(user->id != -1) {
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_REPEAT_LOGIN,"can't repeat login");
        return 0;
    }
    uesdk::User::ptr user_ptr = uesdk::UserManger::loginByFlashToken(std::string(flashToken,flashTokenSize));
    if(!user_ptr){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_LOGIN_FAILe,"login faile");
        return 0;
    }
    user->id = user_ptr->getId();
    return 1;
}

int UeUserLoginThird(UeUser* user,int32_t type,ThirdLoginSuccessCallback successCallback, ThirdLoginFailedCallback faileCallback,void* data, int64_t wait_sec = 300){
    // 先实现多线程再实现这�?
    return 0;
}

int UeGetUserToken(UeUser* user,char** token_out,int* size){
    if(!user || !token_out || !size){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_PARAM_ERROR,"param can't be NULL");
        return 0;
    }

    if(user->id == -1) {
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_NEED_LOGIN,"need login");
        return 0;
    }
    uesdk::User::ptr user_ptr = uesdk::UserMgr::GetInstance()->get(user->id);
    if(!user_ptr){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_NEED_LOGIN,"need login");
        return 0;
    }
    user_ptr->checkAndRefreshToken();
    std::string token = user_ptr->getData<std::string>("token");
    if(token.empty()){
        return 0;
    }
    *token_out = (char*)malloc(token.length()+1);
    memcpy(*token_out,token.c_str(),token.length());
    (*token_out)[token.length()] = '\0';
    *size = token.length();
    return 1;
}

int UeGetFlashUserToken(UeUser* user,char** flashtoken_out,int* size){
    if(!user || !flashtoken_out || !size){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_PARAM_ERROR,"param can't be NULL");
        return 0;
    }

    if(user->id == -1) {
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_NEED_LOGIN,"need login");
        return 0;
    }
    uesdk::User::ptr user_ptr = uesdk::UserMgr::GetInstance()->get(user->id);
    if(!user_ptr){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_NEED_LOGIN,"need login");
        return 0;
    }
    user_ptr->checkAndRefreshToken();
    std::string flashtoken = user_ptr->getData<std::string>("flashToken");
    if(flashtoken.empty()){
        return 0;
    }
    *flashtoken_out = (char*)malloc(flashtoken.length()+1);
    memcpy(*flashtoken_out,flashtoken.c_str(),flashtoken.length());
    (*flashtoken_out)[flashtoken.length()] = '\0';
    *size = flashtoken.length();
    return 1;
}

int UeisUserlogined(UeUser* user){
    if(user->id == -1){
        return 0;
    }
    return 1;
}

int UeGetLastError() {
    return (int32_t)uesdk::ErrorMgr::GetInstance()->getErrorId();
}

const char* UeGetLastErrorMsg() {
    return uesdk::ErrorMgr::GetInstance()->getErrorMsg().c_str();
}

int UePhoneLoginVerify(char * phone,size_t phone_size){
    if(!phone || phone_size <= 0){
        return 0;
    }
    std::string p = std::string(phone,phone_size);
    if(!uesdk::UserManger::phoneSmsVerify(p,uesdk::VerifyType::VERIFY_LOGIN)){
        return 0;
    }
    return 1;
}

int UePhoneRegisterVerify(char * phone,size_t phone_size){
    if(!phone || phone_size <= 0){
        return 0;
    }
    std::string p = std::string(phone,phone_size);
    if(!uesdk::UserManger::phoneSmsVerify(p,uesdk::VerifyType::VERIFY_REGISTER)){
        return 0;
    }
    return 1;
}

int UeEmailRegisterVerify(char * email,size_t email_size){
    if(!email || email_size <= 0){
        return 0;
    }
    std::string p = std::string(email,email_size);
    if(!uesdk::UserManger::emailSmsVerify(p,uesdk::VerifyType::VERIFY_REGISTER)){
        return 0;
    }
    return 1;
}

int UeEmailLoginVerify(char * email,size_t email_size){
    if(!email || email_size <= 0){
        return 0;
    }
    std::string p = std::string(email,email_size);
    if(!uesdk::UserManger::emailSmsVerify(p,uesdk::VerifyType::VERIFY_LOGIN)){
        return 0;
    }
    return 1;
}

int UeGetUserDataString(UeUser* user,char* key,size_t key_len, char** data,size_t* data_len){
    if(!user || user->id == -1){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_NEED_LOGIN,"need login");
        return 0;
    }
    if(!data || !data_len || !key || key_len <= 0){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_PARAM_ERROR,"param can't be NULL");
        return 0;
    }
    *data = NULL;
    *data_len = 0;
    std::string keys(key,key_len);
    uesdk::User::ptr user_ptr = uesdk::UserMgr::GetInstance()->get(user->id);
    if(!user_ptr){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_NEED_LOGIN,"need login");
        return 0;
    }
    std::string value = user_ptr->getData<std::string>(keys);
    if(value.empty()){
        return 0;
    }
    *data = (char*)malloc(value.length()+1);
    memcpy(data,value.c_str(),value.length());
    *data_len = value.length();
    data[value.length()]='\0';
    return 1;
    
}



int UeisPhoneNumber(char * phone,size_t phone_size){
    if(!phone || phone_size<=0){
        return 0;
    }

    std::string val = std::string(phone,phone_size);
    return uesdk::TypeUtil::isPhoneNumber(val);
}

int UeisEmail(char * email,size_t email_size){
    if(!email || email_size <= 0){
        return 0;
    }
    std::string val = std::string(email,email_size);
    return uesdk::TypeUtil::isEmail(val);
}

static UeThirdStatus* UeCreateThirdLogin(const std::string& name){
    uesdk::User::ptr user = uesdk::UserManger::thirdLogin(name);
    if(!user){
        return NULL;
    }
    std::string code = user->getData<std::string>("code");
    std::string authorUrl = user->getData<std::string>("authorUrl");
    std::string verifyCode = user->getData<std::string>("verifyCode");
    if(code.empty() || authorUrl.empty() || verifyCode.empty()){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_DEFAULT,"param can't be empty,code[" 
        + code + "],authorUrl["+authorUrl+"],verifyCode[" + verifyCode + "]");
        return NULL;
    }
    UeThirdStatus* status = (UeThirdStatus*)malloc(sizeof(UeThirdStatus));
    status->authorUrl = strdup(authorUrl.c_str());
    status->check_count = 0;
    status->code = strdup(code.c_str());
    status->verifyCode = strdup(verifyCode.c_str());
    status->third_type = (int)uesdk::StringToThirdPlate(name.c_str());
    return status;
}

UeThirdStatus* UeCreateThirdLoginQQ(){
    return UeCreateThirdLogin("QQ");
}

UeThirdStatus* UeCreateThirdLoginWechat(){
    return UeCreateThirdLogin("Wechat");
}

int UeThirdLoginCheck(UeUser* user,UeThirdStatus* thirdStatus){
    if(!thirdStatus || !(thirdStatus->code) || !(thirdStatus->verifyCode) || !user){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_PARAM_ERROR,"param can't be NULL");
        return 0;
    }
    if(thirdStatus->check_count > 300){
        uesdk::ErrorMgr::GetInstance()->setError(uesdk::UesdkErrorCode::UESDK_ERROR_THIRD_CHECKTOMANYTIMES,"third login check too mang times");
        return 0;
    }
    thirdStatus->check_count++;
    std::string third_name = uesdk::ThirdPlateToString((uesdk::ThirdPlateName)(thirdStatus->third_type));
    std::string code = thirdStatus->code;
    std::string verifyCode = thirdStatus->verifyCode;
    uesdk::User::ptr user_ptr = uesdk::UserManger::thirdLoginCheck(third_name,code,verifyCode);
    if(!user_ptr){
        return -1;
    }
    user->id = user_ptr->getId();
    return 1;

}

int UeRegisterUserByTel(char * user_name, char* password, char* tel, char* verifyCode){
    if(!user_name || !password || !tel || !verifyCode){
        return 0;
    }
    bool ret = uesdk::UserManger::createUserByTel(user_name, password, tel, verifyCode);
    if(ret){
        return 1;
    }
    return 0;
}

int UeRegisterUserByEmail(char * user_name, char* password, char* email, char* verifyCode){
    if(!user_name || !password || !email || !verifyCode){
        return 0;
    }
    bool ret = uesdk::UserManger::createUserByEmail(user_name, password, email, verifyCode);
    if(ret){
        return 1;
    }
    return 0;
}


#ifdef __cplusplus
}
#endif
